[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
この記事では、Scala 3で廃止される「弱適合(Weak Conformance)」について解説します。
Scala 3では、Int
リテラルは必要に応じて他の数値型に変換される
まず、Scala 3での挙動から説明します。
Int
リテラルは、必要に応じて他の数値型に変換されます。
複雑な規則があるのですが、ざっくり言うと「引数リストに、数値型T
とInt
が混ざって渡されている場合」にInt
からT
への変換が行われます。
もしFloat
、Byte
、Short
へ変換されると精度が落ちてしまう場合には、変換されずにAnyVal
に落ち着くことになっています。ご注意ください。
例えば以下で定義される変数list
の型はList[Double]
となります。
val list = List(5.4, 8, math.abs(-4.0), 0, -0.3)
引数リストにDouble
が3つ、Int
が2つ渡されています。
この場合、本来であればInt
とDouble
の共通のスーパークラスであるAnyVal
をとってList[AnyVal]
となるはずですが、その前にInt
をDouble
として扱うことによってList[Double]
へと落ち着くわけです。
Scala 2までの「弱適合」は廃止
以前よりScalaを使用している人はご存知かと思いますが、このような変換はもともと存在しています。
実際のところ、Scala 2では、Int
以外の数値型に対してもリテラルで記述されているかどうかにかかわらず同様の変換が行われています。
この変換は「弱適合(Weak Conformance)」と呼ばれています。
さて、弱適合にはどのような不都合があったのでしょうか。
それは変換の対象範囲です。
「Int
以外の数値型に対しても」「リテラルで記述されているかどうかにかかわらず」という言葉から、変換の対象となる範囲がとても広いことがわかります。
これにより意図しない変換が発生しがちだったことから、修正の対象となりました。
例えば、「Int
以外の数値型に対しても」ですから、Double
, Float
, Long
, Short
, Byte
, Char
が変換されうることになります。
はい、そうです。まさにお気づきのとおりです。Char
も含まれるんです。
Char
がDouble
に変換されて嬉しいのは相当特殊なケースでしょう。他も同様ですから、必要に応じて明示的に変換するよう変更されて当然ではありますね。
また、「リテラルで記述されているかどうかにかかわらず」ですから、メソッドを実行した戻り値を直接渡していたりしても変換されていました。
こちらは少しわかりづらいですが、その箇所で型についての情報を記述するわけではないので、気を抜くと予期せぬ変換が生じる可能性が出てきます。
3.0へアップデートする前に移行しておく
Scala 3.0には弱適合は実装されませんでした。
したがって、Scala 3.0へのアップデートの前に、弱結合を活用している箇所を修正する必要があります。